package com.ruoyi.mp.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.huifu.adapay.Adapay;
import com.huifu.adapay.core.AdapayCore;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.huifu.adapay.core.util.AdapaySign;
import com.huifu.adapay.model.MerConfig;
import com.huifu.adapay.model.Payment;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.db.domain.system.MpClient;
import com.ruoyi.db.domain.system.MpClientOrder;
import com.ruoyi.mp.annotion.Login;
import com.ruoyi.mp.annotion.LoginUser;
import com.ruoyi.mp.config.WxMpConfig;
import com.ruoyi.mp.service.ClientWxMpService;
import com.ruoyi.mp.service.IMpClientOrderService;
import com.ruoyi.mp.service.IMpClientService;
import com.ruoyi.mp.service.impl.ClientWxMpServiceImpl;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * @author chunying.jia
 */
@RestController
@RequestMapping("smp/wechat")
public class WxPayController  extends BaseController {
    private static Logger log = LoggerFactory.getLogger(PcProductController.class);
    @Autowired
    private WxMpConfig wxMpConfig;
    protected ClientWxMpService wxMpService;
    @Autowired
    IMpClientService mpClientService;
    @Autowired
    IMpClientOrderService mpClientOrderService;

    // 初始化用户端微信公众号配置
    @PostConstruct
    public void init() {
        WxMpInMemoryConfigStorage wxMpConfigStorage = new WxMpInMemoryConfigStorage();
        wxMpConfigStorage.setAppId(wxMpConfig.getMyAppId());
        wxMpConfigStorage.setSecret(wxMpConfig.getMyAppSecret());

        wxMpService = new ClientWxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxMpConfigStorage);
    }
    @ApiOperation("一键登录授权连接")
    @GetMapping("/authorize")
    public AjaxResult authorize() {
        init();
        String state ="1";
        System.out.println(wxMpConfig.getMyAppId());
        String redirectURL = wxMpService.oauth2buildAuthorizationUrl("https://www.zaoshanghao.net/#/pages/logins/kongbai", WxConsts.OAuth2Scope.SNSAPI_BASE,
                URLEncoder.encode(state));
        Map<String, Object> map = new HashMap<>();
        map.put("url", redirectURL);
        return AjaxResult.success(map);
    }
    @Login
    @ApiOperation("获取客户openId")
    @GetMapping("/userInfo")
    public AjaxResult userInfo(@RequestParam("code") String code, @LoginUser MpClient client) throws Exception {
        init();
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken;
        try {
            wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
        } catch (WxErrorException e) {
            throw new Exception(e.getError().getErrorMsg());
        }
        String openId = wxMpOAuth2AccessToken.getOpenId();
        System.out.println(openId);
        client.setOpenId(openId);
        mpClientService.updateMpClient(client);
        return AjaxResult.success(openId);
    }
    @Login
    @ApiOperation("返回订单信息")
    @RequestMapping(value = "/weixinpay", method = RequestMethod.GET)
    public AjaxResult weixinpay(MpClientOrder info,@LoginUser MpClient client) throws Exception {
        String apiKey = "api_live_3f414ead-9d1f-4762-a03b-a7a9d47b1f15";
        String mockApiKey = "api_test_6e484e05-93c9-4f6d-a9ff-ee8b3188bdd4";
        String rsaPrivateKey ="MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM7lyUjLhy4z3tVwQPNLVVW2ht9DPZFA+LMp6YjwwvnzAky7Se7kC1t4k+qSqLrwF29dhnez2pmnov2N/bh4FBU3VC+4axTo5DUoRXy7H3Vr9wXZywFefTnCjN1iQfWu2dmWDChQYR7l9bIiwgGGZfvvhG3+NVF1U11t/XKCWZiNAgMBAAECgYAEegBS7ORt4X1uzND68qRUCHD+n6vTWr6G0d9VsS/mzJU+J8c/vfto7UD2EFpKQSugoztnl6KhNHlYVxwoQ6DbkqzFl95QrNOPUQNX4IBjNaldoLIKEGTFEr4bxdg/xfXnT4tIOW5yXS1iCfpSf9vsx6/vsFJ6eWFuHO1fk9+VmQJBAPdFr2Frp9us1Wz+HXmkEefk3TM3peji+FoP/Fc0NFaQgRa/MBLBHy6zCTYoh94nNV2xBs5mF1vPVFBv6NUSawMCQQDWM0hCEnb0nvnOS+fE3UqX03Xotj5+1wMH3kaDSWatjs2VlID1ShnH6la3GHyDVtojNV3AkbNx/uQ4udvGtFEvAkEAw1v4/h0SF4rrbBswqmQoCXBWGxsCJ4b69BzhHvyNxT6R3qjakFaoDjtBMdq/zZJopUcxu2wJVG3vjUV9TKoqhQJASBCO0fPmY5yMzPRKsLgG3Ze+RqHx2ri6A06sCIWMbv3petawoFXi4JidvhIV6hYxY8ETnrMmXUb1P4SARZTq7wJBAL9OXITVnY9UcEHLMe9JMnQ1Cb+K0krYaaIoGEjVagJ3mldSJNeOpF8mCCcv7PDIp1gBFch93Jee5nljV637PGU=";
        MerConfig merConfig = new MerConfig();
        merConfig.setApiKey(apiKey);
        merConfig.setApiMockKey(mockApiKey);
        merConfig.setRSAPrivateKey(rsaPrivateKey);

        Adapay.initWithMerConfig(merConfig);
        //支付接口
        MpClientOrder order = mpClientOrderService.selectByOrderId(info.getOrderId());
        if (order!=null&&order.getOrderStatus()==101l) {
            Map<String, Object> payment = executePayment(info.getOrderId(),client.getOpenId(),order.getOrderAmount());
            return AjaxResult.success(payment);
        }else {
            return AjaxResult.error("订单数据异常");
        }
    }
    @ApiOperation("支付回调接口")
    @PostMapping("/callback")
    public AjaxResult callback(HttpServletRequest request) {
        try {
            //验签请参data
            log.info("回调接口");
            String data = request.getParameter("data");
            log.info(data);
            //验签请参sign
            String sign = request.getParameter("sign");
            //验签标记
            boolean checkSign;
            //验签请参publicKey
            String publicKey = AdapayCore.PUBLIC_KEY;
            //验签
            checkSign = AdapaySign.verifySign(data, sign, publicKey);
            if(checkSign){
                //验签成功逻辑
                JSONObject jsonObject = JSONObject.parseObject(data);
                String status = jsonObject.getString("status");
                if(status.equals("succeeded")){
                    String orderId= jsonObject.get("order_no").toString().substring(jsonObject.get("order_no").toString().indexOf("y")+1);
                    String payAmount= jsonObject.get("pay_amt").toString();
                    MpClientOrder order = mpClientOrderService.selectMpClientOrderByOrderId(orderId);
                    order.setRmbPay(new BigDecimal(payAmount));
                    mpClientOrderService.insertWxClientOrder(order);
                }
                return AjaxResult.success();
            }else {
                //验签失败逻辑
                return AjaxResult.error("验签失败");
            }
        }catch (Exception e){
            return  AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 执行一个支付交易
     *
     * @return 创建的支付对象
     * @throws Exception 异常
     */
    public Map<String, Object> executePayment(String orderId,String openId,BigDecimal pay) throws Exception {
        System.out.println("=======execute payment begin=======");
        //创建支付对象的参数，全部参数请参考 https://docs.adapay.tech/api/index.html
        Map<String, Object> paymentParams = new HashMap<>();

        Map<String,Object> map = new HashMap<>();
        map.put("open_id",openId);
        paymentParams.put("expend",map);
        paymentParams.put("app_id", "app_e894f3a2-2cdb-4405-81d5-59f7ed582aa6");
        //设定延时分账
        paymentParams.put("pay_mode","delay");
        paymentParams.put("order_no", new Date().getTime()+"pay" + orderId);
        paymentParams.put("pay_channel", "wx_pub");
        paymentParams.put("pay_amt", pay.toString());

        paymentParams.put("goods_title", "your goods title");
        paymentParams.put("goods_desc", "your goods desc");

        paymentParams.put("div_members", "");
        //异步通知地址，url为http/https路径，服务器POST回调，URL 上请勿附带参数
        paymentParams.put("notify_url", "http://112.124.58.88:8081/system_mp/smp/wechat/callback");

        //调用sdk方法，创建支付，得到支付对象
        Map<String, Object> payment = new HashMap<>();
        try {
            System.out.println("支付交易，请求参数：" + JSON.toJSONString(paymentParams));
            payment = Payment.create(paymentParams);

        } catch (BaseAdaPayException e) {
            e.printStackTrace();
        }
        System.out.println("支付交易，返回参数：" + JSON.toJSONString(payment));
        System.out.println("=======execute payment end=======");
        return payment;
    }

    /**
     * 关闭一个支付交易
     *
     * @param paymentId 要关闭的支付id
     * @return 关闭的支付对象
     * @throws Exception 异常
     */
    public Map<String, Object> closePayment(String paymentId) throws Exception {
        System.out.println("=======close payment begin=======");
        //关闭支付对象的参数，全部参数请参考 https://docs.adapay.tech/api/index.html
        //调用sdk方法，关闭支付，得到支付对象
        Map<String, Object> payment = new HashMap<>();
        try {
            Map<String, Object> paymentParams = new HashMap<>(10);

            paymentParams.put("payment_id", paymentId);

            // 设置超时时间 单位毫秒 类型 int
            // adapay_connection_request_timeout 类型 int, 单位：毫秒 ms
            // 非必须, 默认 10000 指从连接池获取连接的 timeout
            paymentParams.put("adapay_connection_request_timeout", 1500);
            // adapay_connect_timeout 单位：毫秒 ms
            // 非必须, 默认 30000 指客户端和服务器建立连接的timeout
            paymentParams.put("adapay_connect_timeout", 1500);
            // adapay_socket_timeout 单位：毫秒 ms
            // 非必须, 默认 30000 指客户端从服务器读取数据的timeout，超出后会抛出SocketTimeOutException
            paymentParams.put("adapay_socket_timeout", 1500);

            // 设置网络区域
            // 非必须, 默认 shanghai, 如果要使用其他区域请提交工单备注服务器公网出口IP地址申请开通（如：beijing）
            paymentParams.put("adapay_region", "beijing");


            paymentParams.put("reason", "reason");
            paymentParams.put("expend", "expend");
            paymentParams.put("notify_url", "notify_url");
            System.out.println("关单请求参数：" + JSON.toJSONString(paymentId));
            payment = Payment.close(paymentParams);
        } catch (BaseAdaPayException e) {
            e.printStackTrace();
        }
        System.out.println("关单返回参数：" + JSON.toJSONString(payment));

        System.out.println("=======close payment end=======");
        return payment;
    }

    /**
     * 查询一个支付交易
     *
     * @param paymentId 要查询的支付id
     * @return 查询的支付对象
     * @throws Exception 异常
     */
    public Map<String, Object> queryPayment(String paymentId) throws Exception {
        System.out.println("=======query payment begin=======");
        //查询支付对象的参数，全部参数请参考 https://docs.adapay.tech/api/index.html
        //调用sdk方法，查询支付交易，得到支付对象
        Map<String, Object> payment = new HashMap<>();
        try {
            System.out.println("支付查询请求参数：" + JSON.toJSONString(paymentId));
            payment = Payment.query(paymentId);
        } catch (BaseAdaPayException e) {
            e.printStackTrace();
        }

        System.out.println("支付查询返回参数：" + JSON.toJSONString(payment));
        System.out.println("=======query payment end=======");
        return payment;
    }

}
